package com.lms.service.impl;

import com.lms.bean.Book;
import com.lms.bean.RentRecord;
import com.lms.bean.RentRecordQuery;
import com.lms.bean.User;
import com.lms.dao.BookDao;
import com.lms.dao.RentRecordDao;
import com.lms.dao.UserDao;
import com.lms.service.RentRecordService;
import com.lms.util.QueryResult;
import com.lms.vo.RentRecordVO;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Service
public class RentRecordServiceImpl implements RentRecordService {
    @Autowired
    RentRecordDao rentRecordDao;

    @Autowired
    BookDao bookDao;

    @Autowired
    UserDao userDao;

    @Override
    public Long getTotalCount() {
        return rentRecordDao.count();
    }

    @Override
    public Long getTotalCount(Long rentId) {
        return rentRecordDao.countByRentId(rentId);
    }

    @Override
    public List<RentRecordVO> findAll(int page, int pageSize) {
        Sort sort = Sort.by(Sort.Direction.ASC, "rentId");
        Pageable pageable = PageRequest.of(page, pageSize, sort);
        List<RentRecord> list = rentRecordDao.getList(pageable);
        List<RentRecordVO> rentRecordVOList = new ArrayList<>();
        list.forEach(rentRecord -> rentRecordVOList.add(RentRecordVO.convert(rentRecord)));
        return rentRecordVOList;
    }

    @Override
    public List<RentRecordVO> findAll(int page, int pageSize, Long rentId) {
        Sort sort = Sort.by(Sort.Direction.ASC, "rentId");
        Pageable pageable = PageRequest.of(page, pageSize, sort);
        List<RentRecord> list = rentRecordDao.findByRentId(rentId,pageable);
        List<RentRecordVO> rentRecordVOList = new ArrayList<>();
        list.forEach(rentRecord -> rentRecordVOList.add(RentRecordVO.convert(rentRecord)));
        return rentRecordVOList;
    }

    @Override
    public RentRecord getLastOne() {
        Sort sort = Sort.by(Sort.Direction.ASC, "rentId");
        List<RentRecord> all = rentRecordDao.findAll(sort);
        if(all.size()==0){
            return null;
        }
        return all.get(0);
    }

    @Override
    public QueryResult<RentRecordVO> queryByBookNameLikeOrUsernameLikeOrState(int page, int pageSize, RentRecordQuery param) {
        //拼接查询条件
        Specification<RentRecord> specification = new Specification<RentRecord>() {
            @Override
            public Predicate toPredicate(Root<RentRecord> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if(!StringUtils.isEmpty(param.getUsername())){
                   predicates.add(criteriaBuilder.like(root.<User>get("user").get("username"),"%"+param.getUsername()+"%"));
                }
                if(!StringUtils.isEmpty(param.getBookname())){
                    predicates.add(criteriaBuilder.like(root.<Book>get("book").get("bookName"),"%"+param.getBookname()+"%"));
                }
                if(param.getState()!=null){
                    predicates.add(criteriaBuilder.equal(root.get("state"),param.getState()));
                }
              /*复杂简化一下
              if(predicate1!=null&&predicate2!=null){
                    predicate4 =criteriaBuilder.or(predicate1,predicate2);
                }else if(predicate1!=null){
                    predicate4=predicate1;
                }else if(predicate2!=null){
                    predicate4=predicate2;
                }else if(predicate3!=)
                else{
                    predicate4=criteriaBuilder.ge(root.get("rentId"),-1);
                }*/
                query.where(predicates.toArray(new Predicate[predicates.size()]));//合并查询条件
                return null;
            }
        };
        //构造分页对象
        Sort sort = Sort.by(Sort.Direction.ASC, "rentId");
        Pageable pageable = PageRequest.of(page, pageSize, sort);

        //执行分页查询
        Page<RentRecord> recordPage = rentRecordDao.findAll(specification, pageable);

        //recordPage.getContent();指的是当前页的记录列表，
        List<RentRecord> list = recordPage.getContent();
        List<RentRecordVO> rentRecordVOList = new ArrayList<>();
        list.forEach(rentRecord -> rentRecordVOList.add(RentRecordVO.convert(rentRecord)));

        //组装查询结果
        QueryResult<RentRecordVO> queryResult = new QueryResult<>();
        //recordPage.getTotalElements()指的是当前查询条件下的记录总条数

        queryResult.setTotalCount(recordPage.getTotalElements());
        queryResult.setData(rentRecordVOList);

        return queryResult;

    }

    @Override
    public RentRecord findBy(Long userId, Long bookId) {
        Sort sort = Sort.by(Sort.Direction.ASC, "rentId");
        List<RentRecord> all = rentRecordDao.findAll(sort);
        for (RentRecord rentRecord : all) {
            if(rentRecord.getUser().getUserId().equals(userId)&&rentRecord.getBook().getBookId().equals(bookId)){
                if(!rentRecord.getState()){
                    return rentRecord;
                }
            }
        }

        return null;
    }

    @Override
    public void save(RentRecord rentRecord) {
        Long bookId = rentRecord.getBook().getBookId();
        Book one = bookDao.getOne(bookId);
        rentRecord.setBook(one);
        Long userId = rentRecord.getUser().getUserId();
        User one1 = userDao.getOne(userId);
        rentRecord.setUser(one1);
        rentRecordDao.save(rentRecord);
    }

    @Override
    public RentRecord findById(Long rentId) {
        return rentRecordDao.findById(rentId).orElse(null);
    }

    @Override
    public void delete(Long rentId) {
        rentRecordDao.deleteById(rentId);
    }

    @Override

    public void deleteAll(List<Long> ids) {
        rentRecordDao.deleteAll(ids);
    }

    @Override
    public List<RentRecord> findAll(){
        return rentRecordDao.findAll();
    }


}
